import React, { useState, useEffect } from "react";
import { Button, Modal, Tabs, List, Alert } from "antd";
import { humanFileSize, roundToDecimal } from "@/utils/numbers";
import VirtualList from "rc-virtual-list";
import Operation from "./operation";
import ModalLoadPath from "../ModalLoadPath";
import Folder from "@/media/model/folder.png";
import FolderActive from "@/media/model/folder-active.png";
import ModelIcon from "@/media/model/model-icon.png";
import { invokeAsyncAPi, registerInformApi } from "@/xz-fn.js";
import modelApi from "@/models/model";
import download from "@/utils/download";
import showToast from "@/utils/message";
import System from "@/models/system";
import "./index.css";
const App = ({ showLocalModal, hideLocalDeploy }) => {
  const [loading, setLoading] = useState(false);
  const [categoriesList, setCategoriesList] = useState([]);
  const [open, setOpen] = useState(false);
  const [openLoadPath, setOpenLoadPath] = useState(false);
  const [loadPathInfo, setLoadPathInfo] = useState({
    title: "",
    label: "下载到",
  });
  const [modeList, setModeList] = useState([]);
  const [page, setPage] = useState(1);
  const [firstId, setFirstId] = useState();
  const [secondId, setSecondId] = useState();
  const [installed, setInstalled] = useState(false);
  const [signType, setSignType] = useState("signA");
  const [freeSpace, setFreeSpace] = useState("0");
  const [modelInfo, setModelInfo] = useState({
    id: "",
    active: "",
    title: "",
    logo: "",
    size: 0, //模型大小
    signUrl: "",
    loadUrl: "",
    fileName: "",
    installPath: "",
    loadProgress: "开始下载",
  });
  const [llmInfo, setLlmInfo] = useState({
    size: 0, //ollama大小
    signUrl: "",
    loadUrl: "",
    fileName: "",
    installPath: "",
  });
  const [btnText, setBtnText] = useState("安装");
  const [installInfo, setInstallInfo] = useState();
  const [installModelList, setInstallModelList] = useState();
  const CONTAINER_HEIGHT = 250;
  const pageSize = 20;
  //下载安装模型
  const handleOk = async () => {
    if (!modelInfo?.active) {
      showToast("warning", "请选择需要安装的模型");
      return;
    }
    if (!modelInfo?.installPath) {
      showToast("warning", "请选择需要安装的路径");
      return;
    }
    if (
      (Number(modelInfo?.size) + Number(llmInfo?.size)) / 1024 / 1024 / 1024 >
      freeSpace
    ) {
      //客户端返回的下载地址空间默认时GB
      showToast("warning", "当前存储路径剩余空间不足！");
      return;
    }
    localStorage?.setItem("installPath", modelInfo.installPath);//缓存安装路径,作为下一次的默认安装路径
    if (btnText === "安装") {
      setLoading(true);
      loadOllama();
    }
  };

  //下载模型,item如果存在就是二次下载模型
  const loadModel = async (item = null) => {
    const resData = await download(signType, item || modelInfo);
    if (resData === true) {//下载成功
      followProgress("2");
      setOpenLoadPath(false);
    } else {
      if (resData?.ret == "2") {
        showToast("warning", "磁盘空间不足");
        setOpenLoadPath(true);
        setLoadPathInfo({
          title: "设置下载存储路径",
          label: "下载到",
          btnText: "下载",
          type: "load",
        });
      } else if (resData?.ret == "6") {
        showToast("warning", "请重新登录");
      } else {
        showToast("warning", "下载失败，请稍后重试");
        return;
      }
    }
  };

  //下载ollama
  const loadOllama = async () => {
    const resData = await download(signType, llmInfo);
    if (resData === true) { //下载成功
      setLoading(false);
      followProgress("1");
    } else {
      if (resData?.ret == "2") {
        return "磁盘空间不足";
      } else if (resData?.ret == "6") {
        return "请重新登录";
      } else {
        return "下载失败，请稍后重试";
      }
    }
  };

  //监听下载进度
  const followProgress = (type) => {
    registerInformApi("inform_Download", async (res) => {
      console.log("下载进度", res);
      if (res[0] === "Notify_DownloadProgress") {
        if (type === "1") {//下载ollama
          setBtnText("下载中..." + res[1]?.progress + "%");
        } else if (type === "2") {//下载模型
          if (installed) {//非第一次下载
            setModeList((prevList) =>
              prevList.map((modelItem) =>
                modelItem.id === res[1]?.id
                  ? {
                      ...modelItem,
                      loadProgress: "下载中..." + res[1]?.progress + "%",
                    } // 立即设置为100
                  : modelItem
              )
            );
          } else {
            setBtnText("安装中...");
          }
        }
      } else if (
        res[0] === "Notify_DownloadResult" &&
        Number(res[1]?.ret) === 0
      ) {
        //下载完成
        console.log("下载完成", res);
        if (type === "1") {
          setBtnText("100%");
          setTimeout(() => {
            setBtnText("下载完成");
          }, 500);
          installOllma(res);
        } else if (type === "2") {
          if (installed) {//非第一次下载
            setModeList((prevList) =>
              prevList.map((modelItem) =>
                modelItem.id === res[1]?.id
                  ? { ...modelItem, loadProgress: "100%" } // 立即设置为100
                  : modelItem
              )
            );
            setTimeout(() => {
              setModeList((prevList) =>
                prevList.map((modelItem) =>
                  modelItem.id === res[1]?.id
                    ? { ...modelItem, loadProgress: "下载完成" } // 立即设置为100
                    : modelItem
                )
              );
            }, 500);
          } else {
            setBtnText("安装中...");
          }
          unPackSpace(res);
        }
        setInstallInfo(res);
      } else {
        showToast("warning", "获取下载进度失败，请稍后重试");
        return;
      }
    });
  };

  //安装ollama
  const installOllma = async (item) => {
    const maxSpace = await invokeAsyncAPi("xz_get_max_space_volume");
    const freeSpace = await invokeAsyncAPi("xz_get_current_space_volume", maxSpace)
    if (freeSpace < 15) {//获取当前路径的剩余空间
      showToast("error", "当前存储路径剩余空间不足！");
      setOpenLoadPath(true);
      setLoadPathInfo({
        title: "设置安装存储路径",
        label: "安装到",
        btnText: "安装",
        type: "ollama"
      });
    } else {
      invokeAsyncAPi("xz_InstallAi", maxSpace, maxSpace, 1, 0).then(
        (respon) => {
          console.log("初始化环境变量", respon);
          if (Number(respon) === 0) {
            const path = item[1]?.file;
            invokeAsyncAPi("xz_InstallAi", path, maxSpace, 1, 1).then(
              (data) => {
                console.log("安装", data);
                setTimeout(() => {
                  setBtnText("安装中...");
                }, 500);
                loadModel();
              }
            );
          } else {
            showToast("error", "安装ollama失败");
          }
        }
      );
    }
  };

  //获取模型解压后的大小
  const unPackSpace = (item) => {
    const path = item[1]?.file;
    invokeAsyncAPi("xz_get_unpack_space", path).then(async (res) => {
      console.log("解压大小", res);
      const unPackSpace = res;
      const unPackPath = await invokeAsyncAPi("xz_get_ollama_models_path");
      const freeSpace = await invokeAsyncAPi("xz_get_current_space_volume", unPackPath);
      if (Number(unPackSpace) / 1024 / 1024 / 1024 < Number(freeSpace)) {
        if (installed) {
          setModeList((prevList) =>
            prevList.map((modelItem) =>
              modelItem.id === item[1]?.id
                ? { ...modelItem, loadProgress: "解压部署..." }
                : modelItem
            )
          );
        } else {
          setBtnText("安装中...");
        }
        compressModel(item);
      } else {
        //解压后的文件大小大于解压路径剩余空间
        showToast("error", "磁盘空间不足");
        setOpenLoadPath(true);
        setLoadPathInfo({
          title: "设置安装存储路径",
          label: "安装到",
          btnText: "安装",
          type: "install",
        });
      }
    });
  };

  //解压模型,并监听解压进度
  const compressModel = async (item) => {
    invokeAsyncAPi("xz_get_ollama_models_path").then((respon) => {
      console.log("获取ollama模型路径", respon);
      const path = item[1]?.file;
      followCompress(path, respon, item);
    });
  };

  //监听解压进度
  const followCompress = (path, respon, item) => {
    invokeAsyncAPi("xz_ZipFileUnCompress",(path, val) => {
        console.log(path, val, "解压进度111");
        if (installed) {
          setModeList((prevList) =>
            prevList.map((modelItem) =>
              modelItem.id === item[1]?.id
                ? { ...modelItem, loadProgress: "解压中..." + val + "%" }
                : modelItem
            )
          );
        } else {
          setBtnText("安装中...");
        }
      },
      {
        src_file: path,
        dest_dir: respon,
        deleteSrcFile: false,
      }
    ).then(({ ret, dest_dir, error }) => {
      if (ret === 0) {
        if (installed) {//非第一次下载
          setModeList((prevList) =>
            prevList.map((modelItem) =>
              modelItem.id === item[1]?.id
                ? { ...modelItem, loadProgress: "解压完成" }
                : modelItem
            )
          );
        } else {
          setBtnText("安装完成");
        }
        updateModelList(item);
        console.log(ret, dest_dir, error, "解压进度22222");
      } else {
        showToast("error", "解压失败");
      }
    });
  };

  //更新已经下载模型数据
  const updateModelList = (item) => {
    setModeList((prevList) =>
      prevList.map((modelItem) =>
        modelItem.id === item[1]?.id
          ? { ...modelItem, loadProgress: "部署完成" }
          : modelItem
      )
    );
    let aiList = JSON.parse(localStorage.getItem("installModelList"));
    if (!aiList?.includes(item[1]?.id)) {
      aiList.push(item[1]?.id);
      localStorage.setItem("installModelList", JSON.stringify(aiList));
      getInstallModel();
    }
    setTimeout(() => {
      setModeList((prevList) =>
        prevList.map((modelItem) =>
          modelItem.id === item[1]?.id
            ? { ...modelItem, loadProgress: "已下载" }
            : modelItem
        )
      );
    }, 500);
    const providerType = localStorage.getItem("providerType");
    if (!installed && !providerType) {
      setDefaultModel();
    }
  };

  //首次安装部署成功之，设置默认模型
  const setDefaultModel = async () => {
    const ollamaLLMModelPref = localStorage.getItem("installModelList")
      ? JSON.parse(localStorage.getItem("installModelList"))[0]
      : "";
    const data = {
      LLMProvider: "ollama",
      OllamaLLMAuthToken: "",
      OllamaLLMBasePath: "http://127.0.0.1:11434",
      OllamaLLMKeepAliveSeconds: "300",
      OllamaLLMModelPref: ollamaLLMModelPref,
      OllamaLLMPerformanceMode: "base",
      OllamaLLMTokenLimit: "4096",
    };
    const { error } = await System.updateSystem(data);
    if (error) {
      showToast("error", "模型设置失败");
    } else {
      showToast("success", "模型设置成功");
    }
  };

  const getInstallModel = async () => {
    const aiList = localStorage.getItem("installModelList");
    if (aiList) {
      setInstallModelList(JSON.parse(aiList));
    } else {
      localStorage.setItem("installModelList", JSON.stringify([]));
      setInstallModelList([]);
    }
  };

  //切换tab
  const onChangeTab = (key) => {
    setModeList([]);
    setPage(1);
    setSecondId(key);
    setModelInfo((pre) => ({
      ...pre,
      id: "",
      active: "",
      logo: "",
      title: "",
      size: "0",
      fileName: "",
      signUrl: "",
      loadUrl: "",
    }));
    getModelList(firstId, key, 1);
  };

  //选择模型
  const handleItemClick = (item) => {
    setModelInfo((pre) => ({
      ...pre,
      id: item.id,
      logo: item.logo,
      active: item.title,
      title: item?.title,
      size: item?.content[0]?.fileSize || "0",
      fileName: item?.content[0]?.fileName,
      signUrl: item?.content[0]?.url,
      loadProgress: "开始下载",
    }));
  };

  //选择安装路径/文件夹
  const pickFolder = () => {
    invokeAsyncAPi("xz_PickFolder").then((res) => {
      const resPath = res || "";
      setModelInfo((pre) => ({
        ...pre,
        installPath: resPath,
      }));
      setLlmInfo((pre) => ({
        ...pre,
        installPath: resPath,
      }));
      localStorage?.setItem("installPath", resPath);
    });
  };

  // 获取电脑中，最大空间的路径
  const getMaxSpace = async () => {
    const resPath = await invokeAsyncAPi("xz_get_max_space_volume");
    return resPath || "";
  };

  const handleCancel = () => {
    setOpen(false);
    hideLocalDeploy();
  };

  //滚动到底部加载更多数据
  const onScroll = (e) => {
    if (
      Math.abs(
        e.currentTarget.scrollHeight -
          e.currentTarget.scrollTop -
          CONTAINER_HEIGHT
      ) <= 1
    ) {
      // 只有在当前tab的数据加载完成后才允许加载更多
      if (!loading) {
        setPage((prevPage) => prevPage + 1);
        getModelList(firstId, secondId, page);
      }
    }
  };

  //获取列表
  async function getModelList(firstId, secondId, page, type = "") {
    const { code, data } = await modelApi.list(
      firstId,
      secondId,
      page,
      pageSize
    );
    if (type === "ollama") {//获取ollama数据
      if (code == 200 && data?.item_data?.length) {
        const list = data?.item_data[0] || {};
        list.content = JSON.parse(list.download);
        list.id = list.title + "_123";
        list.loadProgress = "开始下载";
        setLlmInfo((prev) => ({
          ...prev,
          size: list?.content[0]?.fileSize || "0",
          fileName: list?.content[0]?.fileName || "",
          signUrl: list?.content[0]?.url || "",
        }));
      }
    } else {
      if (code == 200) {
        const list = data?.item_data || [];
        if (list?.length) {
          list.forEach((ele) => {
            ele.content = JSON.parse(ele.download);
            ele.id = ele?.content[0]?.model_id || ele.title + "_123";
            ele.loadProgress = "开始下载";
          });
          setModeList((modeList) => [...modeList, ...list]);
          console.log("modeList", list);
          setPage(page + 1);
        } else {
          if (page > 1) {
            showToast("info", "没有更多数据");
          } else {
            setModeList([]);
          }
        }
      } else {
        setModeList([]);
      }
    }
  }

  const clearModelState = () => {
    setModelInfo({
      id: "",
      title: "",
      active: "",
      size: "0",
      signUrl: "",
      loadUrl: "",
      fileName: "",
      installPath: "",
    });
    setLlmInfo({
      size: 0, //ollama大小
      signUrl: "",
      loadUrl: "",
      fileName: "",
      installPath: "",
    });
  };

  useEffect(() => {
    setOpen(showLocalModal);
  }, [showLocalModal]);

  // 卸载
  useEffect(() => {
    return () => {
      // 组件卸载时清理状态
      setModeList([]);
      setPage(1);
      clearModelState();
      setFirstId(null);
      setSecondId(null);
    };
  }, []);

  //获取分类
  useEffect(() => {
    async function getCategoriesList() {
      const { data, code } = await modelApi.categories();
      if (code == 200) {
        if (data?.first_category?.length) {
          const categoriesList = data.first_category.filter((item) => {
            const dateType = JSON.parse(item.attributes)?.datatype;
            return dateType == "models";
          });

          if (!installed) {
            //没有下载安装ollama
            const llmList = data.first_category.filter((item) => {
              const dateType = JSON.parse(item.attributes)?.datatype;
              return dateType == "llm_engine";
            });
            if (llmList?.length) {
              getModelList(
                llmList[0].id,
                llmList[0]?.categories[0].category_id,
                1,
                "ollama"
              );
            }
          }
          if (categoriesList?.length) {
            const signType =
              JSON.parse(categoriesList[0]?.attributes).signType || "signA";
            setSignType(signType);
            const tabList = categoriesList[0].categories.map((item) => {
              return {
                key: item.category_id,
                label: item.title,
                id: item.category_id,
              };
            });
            setFirstId(() => {
              const newPre = categoriesList[0].id;
              return newPre;
            });
            setSecondId(() => {
              const newPre = tabList[0].key;
              return newPre;
            });
            setCategoriesList(tabList);
            getModelList(categoriesList[0].id, tabList[0].key, 1);
          } else {
            setCategoriesList([]);
          }
        } else {
          setCategoriesList([]);
        }
      } else {
        setCategoriesList([]);
      }
    }
    getCategoriesList();
  }, []);

  useEffect(() => {
    const initializeData = async () => {
      try {
        // 并行执行两个异步操作
        const [ollamaStatus, maxSpace] = await Promise.all([
          invokeAsyncAPi("xz_check_ollama_install"),
          getMaxSpace(),
        ]);

        console.log("判断是否安装过ollama", ollamaStatus);
        // 更新状态
        setInstalled(ollamaStatus);
        // 使用函数式更新确保获取最新状态
        if (maxSpace) {
          setModelInfo((prev) => ({
            ...prev,
            installPath: maxSpace,
          }));
          setLlmInfo((prev) => ({
            ...prev,
            installPath: maxSpace,
          }));
        }
      } catch (error) {
        console.error("Error initializing data:", error);
      }
    };

    initializeData();
  }, []); // 空依赖数组，只在组件挂载时执行一次

  //获取路径剩余空间大小
  useEffect(() => {
    invokeAsyncAPi("xz_get_current_space_volume", modelInfo.installPath).then(
      (res) => {
        setFreeSpace(roundToDecimal(res) || 0);
      }
    );
  }, [modelInfo.installPath, llmInfo.installPath]);

  //获取已经安装的模型
  useEffect(() => {
    getInstallModel();
  }, []);
  return (
    <>
      <Modal
        className={`model-deplay ${installed ? "modal-deploy-hide" : ""}`}
        open={open}
        title="本地部署模型"
        onOk={handleOk}
        onCancel={handleCancel}
        centered
        mask={!openLoadPath}
        width={{
          xs: '90%',
          sm: '80%',
          md: '70%',
          lg: '65%',
          xl: '55%',
          xxl: '55%',
        }}
        footer={
          installed
            ? null
            : [
                <div key="foot">
                  <div className="flex items-center mb-[10px]">
                    <span className="text-[13px] color-[#1D2129]">
                      已选择模型：{modelInfo.title}
                    </span>
                  </div>
                  <div className="flex items-center justify-between text-[14px] modal-footer">
                    <div key="load" className="flex items-center flex-1">
                      <span className="text-[13px] color-[#1D2129]">
                        选择下载路径:
                      </span>
                      <div
                        className="p-[8px]  flex-[0.9] flex items-center justify-between mx-[8px] px-[16px] py-[8px] rounded-[8px] border-[1px] border-[#E5E9EF] cursor-pointer"
                        onClick={pickFolder}
                      >
                        <span className="flex-1 truncate mr-[8px] text-left">
                          {modelInfo.installPath}
                        </span>
                        <img
                          src={Folder}
                          alt="Folder"
                          className="w-[18px] h-[18px]"
                        />
                        <input
                          type="file"
                          id="fileInput"
                          style={{ display: "none", opacity: 0 }}
                          onChange={(e) => {
                            console.log("Selected file:", e.target.files[0]);
                          }}
                        />
                      </div>
                      <span className="text-[#86909C]">
                        {humanFileSize(
                          Number(modelInfo.size) + Number(llmInfo.size)
                        )}
                        /{freeSpace}GB
                      </span>
                    </div>
                    <div className="flex items-center justify-between">
                      <Button className="mr-[12px]" onClick={handleCancel}>
                        取消
                      </Button>
                      <Button
                        type="primary"
                        loading={loading}
                        onClick={() => {
                          handleOk();
                        }}
                      >
                        {btnText}
                      </Button>
                    </div>
                  </div>
                </div>,
              ]
        }
      >
        {/* <Alert
          className="alert-warn px-[16px] py-[10px] rounded-[8px] text-[14px] border-none bg-theme-modal-bg"
          message="当前正在下载中，请稍等..."
          type="warning"
          showIcon
          icon={
            <img
              src={Warn}
              alt="Folder"
              className="w-[16px] h-[16px] mr-[8px]"
            />
          }
        />
        <Alert
          className="alert-info px-[16px] py-[10px] rounded-[8px] text-[14px] border-none"
          message="应用模型后，重启应用即可生效"
          type="info"
          showIcon
          icon={
            <img src={Info} alt="Info" className="w-[16px] h-[16px] mr-[8px]" />
          }
        /> */}
        <Tabs
          defaultActiveKey="100"
          items={categoriesList}
          onChange={onChangeTab}
        />
        <List>
          <VirtualList
            data={modeList}
            height={CONTAINER_HEIGHT}
            itemHeight={47}
            itemKey="title"
            onScroll={onScroll}
          >
            {(item) => (
              <List.Item
                key={item.title}
                style={{ padding: "8px 30px 8px 0", borderColor: "#F2F3F5" }}
                className="modal-list-item text-[14px] py-[8px] cursor-pointer"
                onClick={() => {
                  handleItemClick(item);
                }}
              >
                <List.Item.Meta
                  avatar={
                    <img
                      src={item.logo || ModelIcon}
                      alt="Folder"
                      className="w-[100px] h-[54px]"
                    />
                  }
                  title={
                    <span className="modal-list-title text-[14px]">
                      {item.title}
                    </span>
                  }
                  description={
                    <div className="modal-list-description flex flex-col">
                      <p className="text-[10px]">
                        {item.content[0]?.modelTips1}
                      </p>
                      <span className="text-[10px]">
                        {item.content[0]?.modelTips2}
                      </span>
                    </div>
                  }
                />
                {installed ? (
                  <Operation
                    modelInfo={modelInfo}
                    handleLoad={loadModel}
                    listItem={{ ...item }}
                    installModelList={installModelList}
                    getInstallModel={getInstallModel}
                  />
                ) : (
                  <div
                    className={`w-[14px] h-[14px] border-[1px] border-[#E5E6EB] rounded-[7px] ${modelInfo.active == item.title ? "modal-item-active" : ""}`}
                  ></div>
                )}
              </List.Item>
            )}
          </VirtualList>
        </List>
      </Modal>
      {openLoadPath && (
        <ModalLoadPath
          openLoadPath={openLoadPath}
          hideLoadPath={() => setOpenLoadPath(false)}
          loadPathInfo={loadPathInfo}
          modelInfo={modelInfo}
          handleLoad={loadModel}
          handleCompress={unPackSpace}
          handleOllama={installOllma}
          installInfo={installInfo}
        />
      )}
    </>
  );
};
export default App;
